package com.example.myapplication;


import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

public class MainActivity extends AppCompatActivity {
    private TextView local_ip_kj,local_port_kj,remote_ip_kj,remote_port_kj,recv_data_kj;
    private Button startudp_btn_kj,send_btn_kj;
    private ImageView show_cam_kj;
    private EditText msg_kj;
    String local_ip = "192.168.4.1";
    int port = 12345;

    private DatagramSocket socket;  //接收数据用的socket
    int data_len = 1460;//与esp32cam约定的数据传输的长度
    int headFlag = 0;// 0 数据流不是图像数据   1 数据流是图像数据
    byte[] RevBuff = new byte[data_len];//定义接收数据流的包的大小
    byte[] temp = new byte[0];  //存放一帧图像的数据
    Bitmap bitmap = null; //展示图片
    MyHandler myHandler; //处理信息
    String recv_data = ""; //保存接收到的非图像数据
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHandler = new MyHandler();
        show_cam_kj = findViewById(R.id.show_cam_kj);
        local_ip_kj = findViewById(R.id.local_ip_kj);

        local_port_kj = findViewById(R.id.local_port_kj);
        remote_ip_kj = findViewById(R.id.remote_ip_kj);
        remote_port_kj = findViewById(R.id.remote_port_kj);
        msg_kj = findViewById(R.id.msg_kj);
        startudp_btn_kj = findViewById(R.id.startudp_btn_kj);
        send_btn_kj = findViewById(R.id.send_btn_kj);
        recv_data_kj = findViewById(R.id.recv_data_kj);
        //获取本机ip地址
        local_ip = IPUtils.getIpAddress(this);
        Message msg = myHandler.obtainMessage();
        msg.what = 0;
        msg.obj = local_ip;
        myHandler.sendMessage(msg);
        Log.e("IP",local_ip);
//        开启udp服务
        startudp_btn_kj.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //生成接受数据使用的socket
                try {
                    InetAddress serverAdder = InetAddress.getByName(local_ip); //本手机的ip地址
                    socket = new DatagramSocket(port,serverAdder);
                    Message msg = myHandler.obtainMessage();
                    msg.what = 1;
                    msg.obj = "UDP服务开启成功！";
                    myHandler.sendMessage(msg);
//                    开启接收数据的线程
                    new Thread(new RecvData()).start();
                } catch (SocketException | UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        });
//        发送消息
        send_btn_kj.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new SendData()).start();
            }
        });
    }

    public class SendData implements Runnable{

        @Override
        public void run() {
            String server_ip = remote_ip_kj.getText().toString();
            int server_port = Integer.parseInt(remote_port_kj.getText().toString());
            InetAddress server_serverAdder = null;
            try {
                server_serverAdder = InetAddress.getByName(server_ip);
            } catch (UnknownHostException e) {
                throw new RuntimeException(e);
            }
            DatagramSocket send_socket = null;
            try {
                send_socket = new DatagramSocket();
            } catch (SocketException e) {
                throw new RuntimeException(e);
            }
            String tmp = msg_kj.getText().toString();
            byte[] buf = tmp.getBytes();
            DatagramPacket send_packet = new DatagramPacket(buf, buf.length, server_serverAdder, server_port);
            try {
                send_socket.send(send_packet);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            send_socket.close();
        }
    }

    //    接收数据的线程
    public class RecvData implements Runnable {
        public void run() {
            // 接收UDP广播，有的手机不支持
            while (true) {
                byte[] recbuf = new byte[data_len];
                DatagramPacket recpacket = new DatagramPacket(recbuf,
                        recbuf.length);
                try {
                    socket.receive(recpacket);
                    RevBuff = recpacket.getData();
//                                              图像数据包的头  FrameBegin
                    boolean begin_cam_flag = RevBuff[0] == 70 && RevBuff[1] == 114 && RevBuff[2] == 97 && RevBuff[3] == 109 && RevBuff[4] == 101
                            && RevBuff[5] == 66 && RevBuff[6] == 101 && RevBuff[7] == 103 && RevBuff[8] == 105 && RevBuff[9] == 110;
//                            图像数据包的尾  FrameOverr
                    boolean end_cam_flag = RevBuff[0] == 70 && RevBuff[1] == 114 && RevBuff[2] == 97 && RevBuff[3] == 109 && RevBuff[4] == 101
                            && RevBuff[5] == 79 && RevBuff[6] == 118 && RevBuff[7] == 101 && RevBuff[8] == 114 && RevBuff[9] == 114;
                    if (headFlag == 0 && begin_cam_flag) {
                        headFlag = 1;
                    } else if (end_cam_flag) {  //判断包是不是图像的结束包 是的话 将数据传给 myHandler  3 同时将headFlag置0
                        Message msg = myHandler.obtainMessage();
                        msg.what = 3;
                        myHandler.sendMessage(msg);
                        headFlag = 0;
                    } else if (headFlag == 1) { //如果 headFlag == 1 说明包是图像数据  将数据发给byteMerger方法 合并一帧图像
                        temp = byteMerger(temp, RevBuff);
                    }else{
                        //接收到的非图像数据
                        Message msg = myHandler.obtainMessage();
                        msg.what = 2;
                        msg.obj = new String(RevBuff); //字符串长度
                        myHandler.sendMessage(msg);
//                        Log.v("Message:",new String(RevBuff));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    //处理一些不能在线程里面执行的信息
    class MyHandler extends Handler {
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            switch (msg.what){
                case 0:
//                    获取ip c成功
                    local_ip_kj.setText(local_ip);
                    local_port_kj.setText(String.valueOf(port));
                    break;
                case 1:
//                    UDP服务开启成功
                    Toast.makeText((Context) MainActivity.this, msg.obj.toString(),Toast.LENGTH_SHORT).show();
                    break;
                case 2:
//                    处理接收到的非图像数据
//                    Toast.makeText((Context) MainActivity.this, msg.obj.toString(),Toast.LENGTH_SHORT).show();
                    String tmp = recv_data + msg.obj.toString() + "\n";
                    recv_data = tmp;
                    recv_data_kj.setText(tmp);
                    break;
                case 3:
                    try {
                        //处理接受到的图像数据 并展示
                        bitmap = BitmapFactory.decodeByteArray(temp, 0,temp.length);
                        show_cam_kj.setImageBitmap(bitmap);//这句就能显示图片(bitmap数据没问题的情况下) 存在图像闪烁情况 待解决
                        temp = new byte[0];  //一帧图像显示结束  将 temp清零
                    }catch (Exception e){
                        Log.i("Error","Error image data!");
                    }
                    break;
                default: break;
            }
        }
    }

    //    合并一帧图像数据  a 全局变量 temp   b  接受的一个数据包 RevBuff
    public byte[] byteMerger(byte[] a,byte[] b){
        int i = a.length + b.length;
        byte[] t = new byte[i]; //定义一个长度为 全局变量temp  和 数据包RevBuff 一起大小的字节数组 t
        System.arraycopy(a,0,t,0,a.length);  //先将 temp（先传过来的数据包）放进  t
        System.arraycopy(b,0,t,a.length,b.length);//然后将后进来的这各数据包放进t
        return t; //返回t给全局变量 temp
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        socket.close();
    }
}







